from web.models import UserInfo
from django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django_redis import get_redis_connection
from redis.exceptions import ConnectionError
from web.utils.tencent.sms import send_sms_single
from django.conf import settings
from django.db.models import Q

from web.utils.encrypt import md5
import random

class BaseForm(object):
    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        for name,item in self.fields.items():
            item.widget.attrs['class']='form-control'
            item.widget.attrs['placeholder']=f'请输入{item.label}'

class RegisterForm(forms.ModelForm):
    mobile_phone = forms.CharField(validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号格式错误')], label='手机号')
    confirm_password = forms.CharField(widget=forms.PasswordInput(), label='确认密码')
    password = forms.CharField(widget=forms.PasswordInput(), label='密码', min_length=6, max_length=64)
    code = forms.CharField(label='验证码')

    class Meta:
        model = UserInfo
        fields = ['username', 'email', 'password', 'confirm_password', 'mobile_phone', 'code']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs['class'] = 'form-control'
            field.widget.attrs['placeholder'] = f'请输入{field.label}'

    def clean_username(self):
        username = self.cleaned_data['username']
        exists = UserInfo.objects.filter(username=username).exists()
        if exists:
            raise ValidationError('用户名已经存在')
        return username

    def clean_email(self):
        email = self.cleaned_data['email']
        exists = UserInfo.objects.filter(email=email).exists()
        if exists:
            raise ValidationError('该邮箱已经存在')
        return email
    def clean_password(self):
        password=self.cleaned_data['password']
        return md5(password)
    def clean_confirm_password(self):
        password = self.cleaned_data['password']
        confirm_password = md5(self.cleaned_data['confirm_password'])

        if password != confirm_password:
            raise ValidationError('两次密码不一致')
        return confirm_password
    #验证码
    # def clean_code(self):
    #     code=self.cleaned_data['code']
    #     mobile_phone=self.cleaned_data['mobile_phone']
    #     if not mobile_phone:
    #         return code
    #     conn=get_redis_connection()
    #     redis_code=conn.get(mobile_phone)
    #     if not redis_code:
    #         raise ValidationError('验证码已过期|')
    #     redis_code=redis_code.decode()
    #     if code.strip() !=redis_code:
    #         raise ValidationError('验证码不正确')
    #     return code
class MobilePhoneForm(forms.Form):
    '''
    手机发送短信校验
    '''
    type = forms.CharField()
    mobile_phone = forms.CharField(validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号格式错误'), ])

    # phone=forms.CharField()
    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_phone(self):

        mobile_phone = self.cleaned_data['mobile_phone']
        type = self.cleaned_data['type']
        if not type:
            return mobile_phone
            # 校验数据库中是否已经有该手机号
        exists = UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if type == 'register' and exists:
            raise ValidationError('手机号已经存在')
        # 发送短信 & 写入redis
        code = random.randrange(1000, 9999)
        # 发送短信
        # res = send_sms_single(phone, settings.TENCENT_SMS_TEMPLATE, [code, ])
        # if res['result'] != 0:
        #     raise ValidationError(f'短信发送失败,{res["errmsg"]}')
        # 存redis
        conn = get_redis_connection()
        conn.set(mobile_phone, code, ex=60)
        return mobile_phone

class SmsLoginForm(BaseForm,forms.Form):

    mobile_phone=forms.CharField(label='手机号',validators=[RegexValidator(r'^1[3-9]\d{9}$','手机号格式错误'),])
    code=forms.CharField(label='验证码',required=True)

    # def __init__(self,*args,**kwargs):
    #     super().__init__(*args,**kwargs)
    #     for name,item in self.fields.items():
    #         item.widget.attrs['class']='form-control'
    #         item.widget.attrs['placeholder']=item.label
    def clean(self):
        mobile_phone=self.cleaned_data['mobile_phone']
        if not mobile_phone:
            return self.cleaned_data
        exists=UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if not exists:
            self.add_error('mobile_phone','手机号不存在')
            return

        code=self.cleaned_data.get('code')
        if not code:
            self.add_error('code','不能为空')
            return
        try:

            conn=get_redis_connection()
            redis_code=conn.get(mobile_phone)
        except ConnectionError as e:
            self.add_error('code', 'redis链接失败')
            return
        if not redis_code:
            self.add_error('code','验证码过期')
            return
        if code !=redis_code.decode():
            self.add_error('code','验证码错误')
            return
        return self.cleaned_data


class LoginForm(BaseForm,forms.Form):

    name=forms.CharField(label='用户名或邮箱',required=True)
    password=forms.CharField(widget=forms.PasswordInput(),label='密码',required=True)
    code=forms.CharField(label='验证码',required=True)

    def __init__(self,request,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.request=request

    def clean_password(self):
        password=self.cleaned_data['password']
        return md5(password)
    def clean_code(self):
        code=self.cleaned_data.get('code')
        session_code=self.request.session.get('code')
        if not session_code:
            raise ValidationError('验证码过期')
        if code.strip() .upper()!=session_code.upper():
            raise ValidationError('验证码不正确')
        return code

    def clean(self):
        password=self.cleaned_data.get('password')
        name = self.cleaned_data.get('name')
        obj=UserInfo.objects.filter(Q(username=name)|Q(email=name)).filter(password=password).first()
        if not obj:
            self.add_error('name','用户名\密码错误')
            return
        return obj